package com.yuanda.erp9.syn.execule.thread;

import com.yuanda.erp9.syn.entity.CmsOperateErrorLogEntity;
import com.yuanda.erp9.syn.execule.RetryOperateLog;
import com.yuanda.erp9.syn.service.erp9.CmsOperateErrorLogService;
import com.yuanda.erp9.syn.service.erp9.impl.CmsOperateErrorLogServiceImpl;
import com.yuanda.erp9.syn.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.stream.Collectors;

/**
 * @ClassName RetryInsertThread
 * @Description 重试线程, 需要提前启动，保持心跳
 * @Date 2022/11/18
 * @Author myq
 */
@Slf4j
public class RetryOperateLogThread {

    private RetryOperateLogThread() {
    }

    private static final ArrayBlockingQueue<RetryOperateLog> retryQueue = new ArrayBlockingQueue<>(2000000);
    /**
     * 永远不会退出，除非jvm exited
     */
    private static boolean isRunning = true;

    private static RetryOperateLogThread retryOperateLogThread = new RetryOperateLogThread();

    public static RetryOperateLogThread getInstance() {
        return retryOperateLogThread;
    }

    /**
     * @Description: 启动方法
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/11/1810:48
     */
    public void start() {
        RetryOperateLogThread.retry();
    }

    /**
     * @Description: 添加元素
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/12/2214:07
     */
    public void add(RetryOperateLog t) {
        retryQueue.add(t);
    }

    /**
     * @Description: 添加所有
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/12/2214:17
     */
    public void addAll(Collection<? extends RetryOperateLog> e) {
        retryQueue.addAll(e);
    }


    /**
     * @Description: 重试方法
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/11/1810:49
     */
    private static void retry() {
        log.info("****************补偿线程启动*******************");
        Thread retryThread = new Thread(() -> {
            try {
                int count = 0;
                long beginTime = System.currentTimeMillis();
                List<RetryOperateLog> retryOperateLogs = new ArrayList<>();
                while (isRunning) {
                    // 阻塞队列
                    RetryOperateLog poll = retryQueue.poll();
                    if (null != poll) {
                        System.out.println("poll : " + poll.getExceptionMsg());
                        retryOperateLogs.add(poll);
                        if (count++ >= 5000) {
                            retryInsert(retryOperateLogs);
                            count = 0;
                            beginTime = System.currentTimeMillis();
                        }
                        // 计算时间间隔
                        // 当前时间 - 开始时间 > 5秒
                        if ((System.currentTimeMillis() - beginTime) > 5 * 1000) {
                            retryInsert(retryOperateLogs);
                            beginTime = System.currentTimeMillis();
                        }
                    } else {
                        Thread.sleep(500);
                    }
                }

            } catch (Exception e) {
                log.error(">>>>>>>>>>>>>>>>>>补偿线程异常<<<<<<<<<<<<<<<<<<<： " + e);
                e.printStackTrace();
            }
        });
        retryThread.setName("Retry-Operate-Log-Thead");
        retryThread.setDaemon(true);
        retryThread.start();

    }


    /**
     * @Description: 向数据库添加补偿日志
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/12/2214:43
     */
    public static void retryInsert(List<RetryOperateLog> retryOperateLogs) {
        try {
            CmsOperateErrorLogService cmsOperateErrorLogServiceImpl = SpringContextUtil.getBean("cmsOperateErrorLogServiceImpl", CmsOperateErrorLogServiceImpl.class);
            List<CmsOperateErrorLogEntity> collect = retryOperateLogs.parallelStream().map(e -> {
                CmsOperateErrorLogEntity cmsOperateErrorLogEntity = new CmsOperateErrorLogEntity();
                cmsOperateErrorLogEntity.setSupplierId(e.getSupplierId());
                cmsOperateErrorLogEntity.setInsertFailJson(e.getSourceDataJsonString().trim());
                String exceptionMsg = e.getExceptionMsg().trim();
                if (exceptionMsg.length() >= 150) {
                    cmsOperateErrorLogEntity.setExceptionMsg(e.getExceptionMsg().substring(0, 150));
                } else {
                    cmsOperateErrorLogEntity.setExceptionMsg(exceptionMsg);
                }
                cmsOperateErrorLogEntity.setCreateAt(LocalDateTime.now().toString());
                return cmsOperateErrorLogEntity;
            }).collect(Collectors.toList());
            cmsOperateErrorLogServiceImpl.insertBatch(collect);
        } finally {
            retryOperateLogs.clear();
        }
    }


}

